﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MathNet.Numerics.Distributions;

namespace TestTSTree
{
    class Program
    {
        public static double[] setGaussianTable(int length)
        {
            double[] d;
            d = new double[length-1];
            for (int i = 0; i < length - 1; i++)
            {
                Normal normalDist = new Normal();
                d[i] = normalDist.InverseCumulativeDistribution((float)(i+1)/length);
            }
            return d;
        }

        private static int GetIndexInAlphabet(char value)
        {
            // Uses the uppercase character unicode code point. 'A' = U+0042 = 65, 'Z' = U+005A = 90
            char upper = char.ToUpper(value);
            if ((int)upper < 33 || (int)upper > 126)
            {
                throw new ArgumentOutOfRangeException("value", "This method only accepts standard Latin characters.");
            }

            return (int)upper - (int)'A';
        }

        public static float SaxDistance(char c1, char c2, int length)
        {
            double t = 0;
            double[] temp = setGaussianTable(length);

            int c1Index = GetIndexInAlphabet(c1);
            int c2Index = GetIndexInAlphabet(c2);

            if (Math.Abs((c1Index + 1) - (c2Index + 1)) <= 1)
            {
                t += 0;
            }
            else if ((c1Index + 1) < (c2Index + 1) - 1)
            {
                t += Math.Pow(temp[c2Index - 1] - temp[c1Index], 2);
            }
            else if ((c1Index + 1) > (c2Index + 1) - 1)
            {
                t += Math.Pow(temp[c1Index - 1] - temp[c2Index], 2);
            }


            return (float)Math.Sqrt(t);

        }

        public static double w_dist(double current_dist, int p1_index, int p2_index, double[] p1, float[] p2)
        {
            float MAXREAL = (float)9.99e20;
            //Console.WriteLine(p1_index.ToString());
            //Console.WriteLine(current_dist.ToString());
            int length = p1.Length;
            double d1, d2, d3;

            if (p1_index + 1 >= length || p2_index + 1 >= length) d1 = MAXREAL;
            else d1 = Math.Pow(p1[p1_index + 1] - p2[p2_index + 1], 2);

            if (p1_index >= length || p2_index + 1 >= length) d2 = MAXREAL;
            else d2 = Math.Pow(p1[p1_index] - p2[p2_index + 1], 2);

            if (p1_index + 1 >= length || p2_index >= length) d3 = MAXREAL;
            else d3 = Math.Pow(p1[p1_index + 1] - p2[p2_index], 2);

            if (p1_index == length && p2_index == length) return current_dist;
            else
            {
                if (d1 == MAXREAL)
                {
                    if (d2 == MAXREAL)
                    {

                        if (d3 != MAXREAL) return w_dist(current_dist + d3, p1_index + 1, p2_index, p1, p2);
                        else { 
                            return current_dist; }
                    }
                    else
                    {
                        if (d3 != MAXREAL)
                        {
                            return Math.Min(w_dist(current_dist + d2, p1_index, p2_index + 1, p1, p2), w_dist(current_dist + d3, p1_index + 1, p2_index, p1, p2));
                        }
                        else return w_dist(current_dist + d2, p1_index, p2_index + 1, p1, p2);
                    }
                }
                else
                {
                    if (d2 == MAXREAL)
                    {
                        if (d3 != MAXREAL)
                        {
                            return Math.Min(w_dist(current_dist + d1, p1_index + 1, p2_index + 1, p1, p2), w_dist(current_dist + d3, p1_index + 1, p2_index, p1, p2));
                        }
                        else return w_dist(current_dist + d1, p1_index + 1, p2_index + 1, p1, p2);
                    }
                    else
                    {
                        if (d3 != MAXREAL)
                        {
                            return Math.Min(w_dist(current_dist + d1, p1_index + 1, p2_index + 1, p1, p2), Math.Min(w_dist(current_dist + d2, p1_index, p2_index + 1, p1, p2), w_dist(current_dist + d3, p1_index + 1, p2_index, p1, p2)));
                        }
                        else
                        {
                            return Math.Min(w_dist(current_dist + d1, p1_index + 1, p2_index + 1, p1, p2), w_dist(current_dist + d2, p1_index, p2_index + 1, p1, p2));
                        }
                    }
                }
            }


        }

        public static double DTWdistance(double[] p1, float[] p2)
        {
            double current_dist = Math.Pow(p1[0] - p2[0], 2);
           // Console.WriteLine(w_dist(current_dist, 0, 0, p1, p2).ToString()); 
            return Math.Sqrt(w_dist(current_dist, 0, 0, p1, p2));
        }

        static void Main(string[] args)
        {
            //char[] c1 = new char[3];
            ////char[] c2 = new char[3];
            //c1[0] = 'A';
            //c1[1] = 'B';
            //c1[2] = 'C';
            //c2[0] = 'C';
            //c2[1] = 'B';
            //c2[2] = 'A';
            //double d = SaxDistance(c1, c2, 4);
          //  Array.Clear(c1, 0, c1.Length);
          //  Console.WriteLine(c1.Count(x=>x!='\0').ToString());
            //for (int i = 0; i < c1.Length; i++)
            //{
            //    Console.WriteLine(c1[i]);
            //}
            //if ('A' > 'C') Console.WriteLine("A>C");
            //else Console.WriteLine("A<C");
            //int d = (Math.Abs((int)'A' - (int)'E'))/ 2;
            
            //char[] sep;
            //sep = new char[3];

            //if (1==1)
            //{
            //    Console.WriteLine((char)((int)'A' + 2));
            //}
           // Console.WriteLine(SaxDistance('!', '~', 94).ToString());
          //  Console.WriteLine(Convert.ToChar(0 + 65));
           // Console.WriteLine(d.ToString());
          //  double[] test = setGaussianTable(100);
            double[] p1 = {1,4.5,5.3,6.1};
            float[] p2 = {3,1,2,6};
            Console.WriteLine((float)2.5100000e+001);
            Console.ReadLine();
            ////Normal normalDist = new Normal();
            //GetIndexInAlphabet('A');
            //Console.WriteLine(GetIndexInAlphabet('B').ToString());
            //Console.ReadLine();
        }
    }
}
